package com.java.simple.study.juc.p3;

import lombok.extern.slf4j.Slf4j;

import java.util.ArrayList;
import java.util.List;

/**
 * @author zhoujl
 * @date 2022/5/6 21:37
 * @desc 两个线程操作共享变量导致问题
 */
@Slf4j(topic = "c.CounterProblem")
public class CounterProblem {

    private static int counter = 0;
    private static final Object lock = new Object();

    public static void main(String[] args) throws InterruptedException {
        // 引入问题  结果可能 正，负，0
        //m1();
        // synchronized同步  结果为0
        //syncM1();
        // 面向对象改进
        //syncObj();
        // 线程不安全
        test();
    }

    private static Integer i = 0;

    public static void test() {
        List<Thread> list = new ArrayList<>();
        for (int j = 0; j < 2; j++) {
            Thread thread = new Thread(() -> {
                for (int k = 0; k < 5000; k++) {
                    // 这里无法锁住i 因为Integer是final类 每次i++相当于重新赋值
//                    synchronized (i){
                    synchronized (CounterProblem.class) {
                        i++;
                    }

                }
            }, "t" + j);
            list.add(thread);
        }
        list.forEach(Thread::start);
        list.forEach(t -> {
            try {
                t.join();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        });
        log.debug("{}", i);
    }

    public static void syncObj() throws InterruptedException {
        Room room = new Room();
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                room.incr();
            }
        }, "t1");
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                room.deIncr();
            }
        }, "t2");
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        log.debug("{}", room.getValue());
    }


    public static void syncM1() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            synchronized (lock) {
                for (int i = 0; i < 5000; i++) {
                    counter++;
                }
            }
        }, "t1");
        Thread t2 = new Thread(() -> {
            synchronized (lock) {
                for (int i = 0; i < 5000; i++) {
                    counter--;
                }
            }
        }, "t2");
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        log.debug("{}", counter);
    }

    public static void m1() throws InterruptedException {
        Thread t1 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                counter++;
            }
        }, "t1");
        Thread t2 = new Thread(() -> {
            for (int i = 0; i < 5000; i++) {
                counter--;
            }
        }, "t2");
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        log.debug("{}", counter);
    }

}

class Room {
    // 多个线程对此成员变量进行共享
    int value;

    public void incr() {
        synchronized (this) {
            value++;
        }
    }

    public void deIncr() {
        synchronized (this) {
            value--;
        }
    }

    public int getValue() {
        synchronized (this) {
            return value;
        }
    }

}
